/**
 * File: StoredMatchMaqLoadController.java
 * Created by: mhaimel
 * Created on: 19 Aug 2009
 * CVS:  $Id: StoredMatchMaqLoadController.java,v 1.2 2009/11/24 16:31:20 mhaimel Exp $
 */
package uk.ac.ebi.curtain.controller.loader;

import java.io.File;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import java.util.concurrent.Future;
import java.util.concurrent.atomic.AtomicReference;

import uk.ac.ebi.curtain.controller.ParallelSingleSubmitController;
import uk.ac.ebi.curtain.controller.SimpleReport;
import uk.ac.ebi.curtain.controller.loader.impl.ConcurrentMatchHandler;
import uk.ac.ebi.curtain.management.IControllerReport;
import uk.ac.ebi.curtain.processor.load.impl.StoredMatchMaqLoadProcessor;
import uk.ac.ebi.curtain.processor.writer.BucketCollectionBean;
import uk.ac.ebi.curtain.utils.data.ReadType;

/**
 * @author mhaimel
 *
 */
public class StoredMatchMaqLoadController extends ParallelSingleSubmitController<BucketCollectionBean, BucketCollectionBean, StoredMatchMaqLoadProcessor> {
	private AtomicReference<ConcurrentMatchHandler> pairedMatchHandler = new AtomicReference<ConcurrentMatchHandler>(new ConcurrentMatchHandler());
	private AtomicReference<ConcurrentMatchHandler> unpairedmatchHandler = new AtomicReference<ConcurrentMatchHandler>(new ConcurrentMatchHandler());
	private volatile List<BucketCollectionBean> inputList = Collections.emptyList();	
	
	@Override
	protected void singleSubmit(List<BucketCollectionBean> inputList) {
		this.inputList = inputList;
		long cnt = 0;
		/* Initialise paired / unpaired Match handler */
		for(BucketCollectionBean input : inputList){
			Set<String> cIds = input.getContigs();
			for(String id : cIds){
				++cnt;
				getPairedMatchHandler().registerContig(id);
				getUnpairedMatchHandler().registerContig(id);
			}
		}
		getLog().debug("Registered contigs: " + cnt);
		/* submit Paired handler - one for each Read type */
		for(ReadType rt : ReadType.getPaired()){
			File file = getContext().currentFiles().getEntryMapPosition(rt);
			if(file.exists()){
				StoredMatchMaqLoadProcessor pairedJob = getContext().getInjector().getInstance(StoredMatchMaqLoadProcessor.class);	
				pairedJob.setDataMapFile(file);
				pairedJob.setMatchHandler(getPairedMatchHandler());
				getLog().info("Submit paired map handler for type " + rt);
				submit(pairedJob);
			}
		}
		
		/* submit Unpaired handler - one for each Read type */
		for(ReadType rt : ReadType.getUnpaired()){
			File file = getContext().currentFiles().getEntryMapPosition(rt);
			if(file.exists()){
				StoredMatchMaqLoadProcessor unpairedJob = getContext().getInjector().getInstance(StoredMatchMaqLoadProcessor.class);	
				unpairedJob.setDataMapFile(file);
				unpairedJob.setMatchHandler(getUnpairedMatchHandler());
				getLog().info("Submit unpaired map handler for type " + rt);
				submit(unpairedJob);
			}
		}
	}

	private ConcurrentMatchHandler getUnpairedMatchHandler() {
		return unpairedmatchHandler.get();
	}
	
	@Override
	protected void processResult(Future<BucketCollectionBean> res,StoredMatchMaqLoadProcessor job) {
		extractResult(res, job); // to get possible exceptions through
		// do nothing
	}
	
	private void _processResults() {
		for(BucketCollectionBean bean : inputList){
			for(String contig : bean.getContigs()){
				Set<String> reads = getPairedMatchHandler().getReadsForContig(contig);
				if(null != reads){
					bean.getPaired_reads().addAll(reads);
				}
			}
			for(String contig : bean.getContigs()){
				Set<String> reads = getUnpairedMatchHandler().getReadsForContig(contig);
				if(null != reads){
					bean.getUnpaired_reads().addAll(reads);
				}
			}
			interceptorHandle(bean);
		}
		inputList.clear();
	}
	
	@Override
	protected void doShutdown(){
		// once all the files are read in - sort the results to the according buckets
		_processResults();
		inputList = Collections.emptyList();
		getPairedMatchHandler().reset();
		pairedMatchHandler.set(null);
		getUnpairedMatchHandler().reset();
		unpairedmatchHandler.set(null);
		super.doShutdown();
	}

	@Override
	protected IControllerReport getReturnCall() {
		return new SimpleReport("Finished");
	}
	
	private ConcurrentMatchHandler getPairedMatchHandler() {
		return pairedMatchHandler.get();
	}
}
